function nextNumber(num) {
    num += 1;
    num = num > 9 ? 1 : num;
    return num;
}

function generateRow() {
    let arr = []
    for (let i = 0; i < 9; i++) {
        arr[i] = i + 1;
    }
    return arr
}

export const row_contains = (arr, num) => {
    if (arr == null) {
        return false;
    }
    for (let j of arr) {
        if (j && j.value === num) {
            return true;
        }
    }
    return false;
}

export const column_contains = (arr, column, num) => {
    for (let j of arr) {
        if (!j[column]) {
            return false
        }
        if (j[column].value === num) {
            return true;
        }
    }
    return false;
}

export const block_contains = (arr, i, j, num) => {
    let row = Math.floor(i / 3) * 3;
    let column = Math.floor(j / 3) * 3
    let temp = [];
    for (let k = row; k < row + 3; k++) {
        for (let l = column; l < column + 3; l++) {
            if (arr[k] && arr[k][l]) temp[(k - row) * 3 + (l - column)] = {value: arr[k][l]};
        }
    }
    return row_contains(temp, num);
}

function switchRow(arr, i, j) {
    for (let k = 0; k < arr[i].length; k++) {
        let temp = arr[i][k];
        arr[i][k] = arr[j][k];
        arr[j][k] = temp;
    }
}

function switchColumn(arr, i, j) {
    for (let k = 0; k < arr.length; k++) {
        let temp = arr[k][i];
        arr[k][i] = arr[k][j];
        arr[k][j] = temp;
    }
}

function random(seeds) {
    return Math.ceil(Math.random() * seeds)
}

function switchRowAndColumn(arr) {
    let times = random(40) + 10;
    for (let i = 0; i < times; i++) {
        {
            let j = random(3) - 1;
            let k = random(3) - 1;
            if (j !== k) switchRow(arr, j, k);
        }
        {
            let j = random(3) - 1;
            let k = random(3) - 1;
            if (j !== k) switchRow(arr, j + 3, k + 3);
        }
        {
            let j = random(3) - 1;
            let k = random(3) - 1;
            if (j !== k) switchRow(arr, j + 6, k + 6);
        }
        {
            let j = random(3) - 1;
            let k = random(3) - 1;
            if (j !== k) switchColumn(arr, j, k);
        }
        {
            let j = random(3) - 1;
            let k = random(3) - 1;
            if (j !== k) switchColumn(arr, j + 3, k + 3);
        }
        {
            let j = random(3) - 1;
            let k = random(3) - 1;
            if (j !== k) switchColumn(arr, j + 6, k + 6);
        }
    }
}

function clearCells(level, arr) {
    let min, max;

    switch (level) {
        case 1:
            min = 20;
            max = 10;
            break;
        case 2:
            min = 30;
            max = 10;
            break;
        case 3:
            min = 35;
            max = 10;
            break;
        default:
            min = 45;
            max = 5;
            break;
    }

    let count = random(max) + min
    for (let i = 0; i < count; i++) {
        do {
            let n = random(9) - 1;
            let m = random(9) - 1;
            if (arr[n][m] > 0) {
                arr[n][m] = undefined
                break;
            }
        } while (true);
    }
}

export const init = (level) => {
    let result = [];
    result[0] = generateRow();
    for (let i = 1; i < 9; i++) {
        result.push([])
        for (let j = 0; j < 9; j++) {
            let number = nextNumber(result[i - 1][j]);
            while (row_contains(result[i], number) || column_contains(result, j, number) || block_contains(result, i, j, number)) {
                number = nextNumber(number);
            }
            result[i][j] = number;
        }
    }
    switchRowAndColumn(result);
    clearCells(level, result);
    return result;
}